//////////////////////////////////////////////
// Program.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward declarations ---------------------

namespace nkGraphics
{
	class ProgramSourcesHolder ;
	class StreamOutputDescriptor ;
	class System ;
}

/// Includes ---------------------------------

// nkGraphics
#include "../Dll/DllDefines.h"

#include "../Resources/Resource.h"

#include "Enums/ProgramCompilationProfile.h"

#include "ProgramCompilationResult.h"
#include "ProgramType.h"

// Export
#include <NilkinsExport/Exportable/Exportable.h>

// nkMemory
#include <NilkinsMemory/Containers/BufferView.h>
#include <NilkinsMemory/Containers/String.h>
#include <NilkinsMemory/Containers/StringView.h>

#include <NilkinsMemory/Pointers/UniquePtr.h>

// Standards
#include <vector>

/// Internals --------------------------------

namespace nkGraphics
{
	struct ProgramSemanticEntry
	{
		nkMemory::String _name ;
		unsigned int _index ;
	} ;
}

/// Class ------------------------------------
	
namespace nkGraphics
{
	class DLL_GRAPHICS_EXPORT Program : public Resource, public nkExport::Exportable
	{
		public :
		
			// Destructor
			virtual ~Program () ;

			// Getters
			const ProgramCompilationResult& getLastCompilationResult () const ;
			bool isFromFile () const ;
			bool isFromMemory () const ;
			const ProgramSourcesHolder& getMemory () const ;
			nkMemory::BufferView<const ProgramSemanticEntry> getInputSemantics () const ;
			unsigned int getId () const ;
			PROGRAM_TYPE getType () const ;
			PROGRAM_COMPILATION_PROFILE getProfile () const ;

			// Setters
			virtual void setFromMemory (const ProgramSourcesHolder& memory) ;
			virtual void setDefines (const ProgramSourcesHolder& memory) ;
			void setFromFiles (nkMemory::StringView folder) ;
			void setFileExtensions (nkMemory::StringView value) ;
			void setId (unsigned int id) ;
			void setProfile (PROGRAM_COMPILATION_PROFILE profile) ;
			void setActivateCrossCompilerDefines (bool value) ;

			// Fonctions de chargement
			bool prepareMemoryWithFiles () ;
			virtual bool loadFromMemory () = 0 ;
			virtual bool tryToLoadFrom (ProgramSourcesHolder& newMemory) = 0 ;

			// Load brut
			virtual bool load () override ;
			virtual void unload () override ;			

			// Import / Export
			virtual void exportClassToTree (nkExport::Node* rootNode) override ;
			virtual void importClassFromTree (nkExport::Node* rootNode) override ;

		public :

			// Statics
			static nkMemory::UniquePtr<Program> create (System* system = nullptr) ;

		protected :

			// Functions
			// Constructor
			Program (System* system) noexcept ;

		protected :

			// Attributes
			// Last compilation result
			ProgramCompilationResult _lastCompilationResult ;

			// Memory, sources or extension to seek
			nkMemory::String _fileExtensions ;
			nkMemory::UniquePtr<ProgramSourcesHolder> _memory ;

			// Semantics that the shader requires
			std::vector<ProgramSemanticEntry> _inputSemantics ;

			// Id for sorting
			unsigned int _id ;

			// Type of program inside
			PROGRAM_TYPE _type ;
			// Compilation profile
			PROGRAM_COMPILATION_PROFILE _profile ;

			// Flags
			bool _fromFile ;
			bool _filesLoaded ;
			bool _fromMemory ;
			bool _activateCrossCompilerDefines ;
	} ;
}